/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"

#include "S_Scene.h"

#include "S_键值序列容器.h"

#include <time.h>
#include <几何图形/图形相交.h>
#include "底层绘图/底层绘图框架.h"
#include "底层绘图/S_纹理.h"
#include "纹理/纹理.h"
#include "面/面.h"

#include "core/引擎配置.h"

#include "matXX.h"

//#include <vulkan/vulkan.h>
//static S_键值序列容器<uint32, S_Scene*> g_场景容器;




static double dur;
static clock_t start, end;

static float32 g线拾取距离 = 0.1;



S_Scene::S_Scene(uint32 id_name) :S_Object(id_name), m_重新录制绘图命令(true) {
	m_ID = id_name;
	m_帧 = 0;
	//m_绘图框架 = 0;

	start = clock();


	mf_渲染前Update = 0;

	m_拾取树 = f_空间划分_create球形八叉树(0.1);


	//构建光追后端
	m_光追后端 = nullptr;
	
	m_矩形区域光几何ID = S_Object::m_ID生成器.f_Gen();
	m_圆形区域光几何ID = S_Object::m_ID生成器.f_Gen();


	m_光追顶层加速结构 = {};
	m_光追网格对象 = {};
}

S_Scene::~S_Scene() {
	mf_渲染前Update = 0;

	m_物体.clear();
	m_物体set.clear();

	f_空间划分_destroy球形八叉树(m_拾取树);
}



void S_Scene::f_Update(S_摄像机* camera) {
	//S_渲染参数 渲染参数;
	if(camera && camera->m_isUpdate) camera->f_Update(nullptr);
	
	for (auto& e : m_物体) {
		e->f_Update(nullptr, nullptr);
	}

	for (auto& e : m_物体set) {
		e->f_Update(nullptr, nullptr);
	}
	//m_Physics.f_模拟();
	//m_Physics.f_应用变换到物体();
	if (mf_渲染前Update) {
		mf_渲染前Update((S_结构对象指针)this);
	}
	//更新动画
	S_物体::g_更新曲线关键帧 = false;

}

void S_Scene::f_Render(S_摄像机* camera, const vec2& size, const vec2& offset) {
	S_Viewport	视口 = { offset.x, offset.y, size.x, size.y, 0.0f, 1.0f};
	//S_Rect2D	裁剪 = { {}, uvec2{uint32(size.x), uint32(size.y)}};
	S_Rect2D	裁剪 = { _iVec2(offset), uvec2{uint32(size.x), uint32(size.y)} + _uVec2(offset) };
	
	S_渲染参数 渲染参数;
	渲染参数.m_视图投影矩阵 = camera->m_投影矩阵;
	渲染参数.m_视口 = &视口;
	渲染参数.m_裁剪 = &裁剪;

	for (auto& e : m_物体set) {
		e->f_绘制(渲染参数);
	}
	for (auto& e : m_物体) {
		e->f_绘制(渲染参数);
	}

	return;
}

void S_Scene::f_RayRender(S_摄像机* camera, uvec2 viewSize, S_纹理& tex, uint32 采样) {

	if (m_光追后端->m_重新编译线管) {
		m_光追后端->f_重构材质线管();
		m_光追后端->m_重新编译线管 = false;
	}

	int32 需要要加载纹理 = 0;
	S_光追后端::g_资源分配内存锁.lock();

	需要要加载纹理 = m_光追后端->m_待加载纹理列队.size();
	if (需要要加载纹理) {
		for (auto& tex : m_光追后端->m_待加载纹理列队) {
			if (tex.m_内存数据) {
				f_tex_加载图像到GPU(tex, m_光追后端->m_渲染命令缓存);

				free(tex.m_内存数据);
				tex.m_内存数据 = nullptr;
				--需要要加载纹理;

				m_光追后端->f_set纹理(tex.m_纹理对象);
			}
		}
		m_光追后端->m_待加载纹理列队.clear();

		for (auto& e : m_光追后端->G纹理) {
			m_光追后端->f_set纹理((S_纹理*)e.m_Ptr);
		}
	}

	S_光追后端::g_资源分配内存锁.unlock();

#pragma omp parallel sections
	{
#pragma omp section
		{
			
		}
#pragma omp section
		{
			if (m_重新录制绘图命令) {
				m_光追后端->f_清除几何加速结构();

				for (auto& e : m_物体set) {
					f_构建底层光追加速结构(e);
				}

				m_光追后端->f_添加底层加速结构(m_光追后端->m_区域光物体网格, m_矩形区域光几何ID, E_物体类型::t_区域光_方形);
				m_光追后端->f_添加底层加速结构(m_光追后端->m_区域光物体网格, m_圆形区域光几何ID, E_物体类型::t_区域光_圆形);

				m_光追后端->f_重置渲染帧记录();
				m_重新录制绘图命令 = false;
			}

			if (m_重新录制光追灯光) {
				uint32 id = 0;
				std::vector<S_LigthParallel> 平行光参数组(m_灯光.size());
				for (auto& e : m_灯光) {
					平行光参数组[id] = *f_ob_fromParallelLigth(e);
				}
				m_光追后端->f_填充平行光参数(平行光参数组);
				m_重新录制光追灯光 = false;
			}

			uint32 id = 0;
			for (auto& e : m_物体set) {
				f_构建顶层光追加速结构(e, id);
			}
			m_光追后端->f_构建顶层加速结构(id);

		}
	}
	
	if(需要要加载纹理 > 0) return;


	m_光追后端->m_参数布局.m_参数槽[0] = m_光追后端->m_顶层加速结构;
	m_光追后端->m_参数布局.m_参数类型[0] = E_板载缓存类型::e_光追BVH;
	m_光追后端->m_参数布局.m_绑定位置[0] = 0;
	m_光追后端->m_参数布局.m_绑定数量[0] = 1;

	m_光追后端->m_参数布局.m_参数槽[1] = &tex;
	m_光追后端->m_参数布局.m_参数类型[1] = E_板载缓存类型::e_IMAGE;
	m_光追后端->m_参数布局.m_绑定位置[1] = 1;
	m_光追后端->m_参数布局.m_绑定数量[1] = 1;

	m_光追后端->m_参数布局.m_参数槽[2] = camera->m_投影矩阵;
	m_光追后端->m_参数布局.m_参数类型[2] = E_板载缓存类型::e_UBO;
	m_光追后端->m_参数布局.m_绑定位置[2] = 2;
	m_光追后端->m_参数布局.m_绑定数量[2] = 1;

	m_光追后端->m_参数布局.m_参数槽[3] = m_光追后端->m_场景物体网格指针;
	m_光追后端->m_参数布局.m_参数类型[3] = E_板载缓存类型::e_SSBO;
	m_光追后端->m_参数布局.m_绑定位置[3] = DEF_ObMeshBindID;
	m_光追后端->m_参数布局.m_绑定数量[3] = 1;

	m_光追后端->m_参数布局.m_参数槽[4] = m_光追后端->m_材质;
	m_光追后端->m_参数布局.m_参数类型[4] = E_板载缓存类型::e_SSBO;
	m_光追后端->m_参数布局.m_绑定位置[4] = DEF_MaterialsBindID;
	m_光追后端->m_参数布局.m_绑定数量[4] = 1;


	m_光追后端->m_参数布局.m_参数槽[5] = m_光追后端->m_帧渲染信息;
	m_光追后端->m_参数布局.m_参数类型[5] = E_板载缓存类型::e_UBO;
	m_光追后端->m_参数布局.m_绑定位置[5] = DEF_RenderFrameBindID;
	m_光追后端->m_参数布局.m_绑定数量[5] = 1;

	m_光追后端->m_参数布局.m_参数槽[6] = m_光追后端->m_平行光缓冲区;
	m_光追后端->m_参数布局.m_参数类型[6] = E_板载缓存类型::e_SSBO;
	m_光追后端->m_参数布局.m_绑定位置[6] = DEF_ParallelLightBindID;
	m_光追后端->m_参数布局.m_绑定数量[6] = 1;

	m_光追后端->m_参数布局.m_参数槽[7] = m_光追后端->f_get纹理();
	m_光追后端->m_参数布局.m_参数类型[7] = E_板载缓存类型::e_IMAGE_SAMPLER;
	m_光追后端->m_参数布局.m_绑定位置[7] = DEF_TexturesBindID;
	m_光追后端->m_参数布局.m_绑定数量[7] = m_光追后端->f_get纹理数量();
	//m_光追后端->m_参数布局.m_绑定数量[7] = 0;

	m_光追后端->m_参数布局.m_参数槽[8] = m_光追后端->m_几何属性;
	m_光追后端->m_参数布局.m_参数类型[8] = E_板载缓存类型::e_SSBO;
	m_光追后端->m_参数布局.m_绑定位置[8] = DEF_BINDING_Render_Geom;
	m_光追后端->m_参数布局.m_绑定数量[8] = 1;

	m_光追后端->m_参数布局.m_参数槽[9] = m_光追后端->m_全局绑定参数指针;
	m_光追后端->m_参数布局.m_参数类型[9] = E_板载缓存类型::e_SSBO;
	m_光追后端->m_参数布局.m_绑定位置[9] = DEF_BINDING_Render_GlobalParam;
	m_光追后端->m_参数布局.m_绑定数量[9] = 1;

	f_df_setGPU参数槽(m_光追后端->m_Ctx->m_逻辑设备.设备, m_光追后端->m_GPU参数设置, m_光追后端->m_参数布局);

	if (采样) {
		m_光追后端->f_Rander(viewSize, 采样);
	}
	else {
		m_光追后端->f_Rander(viewSize);
	}
	
	
	//m_光追后端->f_递增渲染帧记录();
}


void S_Scene::f_构建底层光追加速结构(S_物体* ob) {
	if (ob->m_渲染) {
		switch (ob->m_Type) {
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格: {
			auto me = f_ob_fromMesh(ob, 1);
			if(me->m_索引->m_Mem.m_大小) {
				m_光追后端->f_添加底层加速结构(me, ob->m_globalID, ob->m_Type);
			}
			break;
		}

		//case E_物体类型::t_包: {
		//	if (!ob->m_变换矩阵.m_Mem.m_大小) break;
		//
		//	uint32 几何ID = ob->m_ID;
		//	auto* mat = f_buf_Mat44_ptr(ob->m_变换矩阵);
		//	for (uint32 i = 0; i < ob->m_变换矩阵.m_Mem.m_大小; ++i) {
		//		switch (ob->m_子物体[i]->m_Type) {
		//		case E_物体类型::t_区域光_方形: 几何ID = m_矩形区域光几何ID; break;
		//		case E_物体类型::t_区域光_圆形: 几何ID = m_圆形区域光几何ID; break;
		//		default:
		//			continue;
		//		}
		//	}
		//	
		//}
						 

		case E_物体类型::t_区域光_方形: {
			if (m_矩形区域光几何ID >= m_光追后端->m_场景物体网格指针->m_Size) f_buf_resize(m_光追后端->m_场景物体网格指针, m_矩形区域光几何ID + 1);

			S_Mesh* me = m_光追后端->m_区域光物体网格;
			S_ObMesh mesh = {
				f_buf_getAddress(*me->m_顶点),
				f_buf_getAddress(*me->m_UV),
				f_buf_getAddress(*me->m_UV索引),
				f_buf_getAddress(*me->m_索引),
				f_buf_getAddress(*me->m_面),
				DEF_ObType_Ligth,
				0,
			};
			f_buf_set<S_ObMesh>(m_光追后端->m_场景物体网格指针, m_矩形区域光几何ID, mesh);
			break;
		}
		case E_物体类型::t_区域光_圆形: {
			if (m_圆形区域光几何ID >= m_光追后端->m_场景物体网格指针->m_Size) f_buf_resize(m_光追后端->m_场景物体网格指针, m_圆形区域光几何ID + 1);

			S_Mesh* me = m_光追后端->m_区域光物体网格;
			S_ObMesh mesh = {
				f_buf_getAddress(*me->m_顶点),
				f_buf_getAddress(*me->m_UV),
				f_buf_getAddress(*me->m_UV索引),
				f_buf_getAddress(*me->m_索引),
				f_buf_getAddress(*me->m_面),
				DEF_ObType_Ligth,
				0,
			};
			f_buf_set<S_ObMesh>(m_光追后端->m_场景物体网格指针, m_圆形区域光几何ID, mesh);
			break;
		}

		default:
			break;
		}

		for (auto& ob : ob->m_子物体) {
			f_构建底层光追加速结构(ob);
		}
	}
}

void S_Scene::f_构建顶层光追加速结构(const S_物体* ob, uint32& offset) {
	switch (ob->m_Type) {
	case E_物体类型::t_多边形: 
	case E_物体类型::t_网格: {
		S_Mesh* me = f_ob_fromMesh(ob, 1);
		if (me->m_索引->m_Mem.m_大小) {
			auto* mat = f_buf_Mat44_ptr(ob->m_变换矩阵);
			for (uint32 i = 0; i < ob->m_变换矩阵.m_Mem.m_大小; ++i) {
				m_光追后端->f_更新实例变换(f_mat3x4_转换(mat[i]), offset, ob->m_globalID);
				++offset;
			}
		}
		break;
	}
	
	case E_物体类型::t_包: {
		if(!ob->m_变换矩阵.m_Mem.m_大小) break;
		uint32 几何ID = ob->m_ID;
		auto* mat = f_buf_Mat44_ptr(ob->m_变换矩阵);
		for (uint32 i = 0; i < ob->m_变换矩阵.m_Mem.m_大小; ++i) {
			switch (ob->m_子物体[i]->m_Type) {
			case E_物体类型::t_区域光_方形: 几何ID = m_矩形区域光几何ID; break;
			case E_物体类型::t_区域光_圆形: 几何ID = m_圆形区域光几何ID; break;
			default:
				continue;
			}
			m_光追后端->f_更新实例变换(f_mat3x4_转换(mat[i]), offset, 几何ID, ob->m_子物体[i]->m_ID, 1);

			S_Mesh* me = m_光追后端->m_区域光物体网格;
			S_ObMesh mesh = {
				f_buf_getAddress(*me->m_顶点),
				f_buf_getAddress(*me->m_UV),
				f_buf_getAddress(*me->m_UV索引),
				f_buf_getAddress(*me->m_索引),
				f_buf_getAddress(*me->m_面),
				DEF_ObType_Ligth,
				0,
			};
			f_buf_set<S_ObMesh>(m_光追后端->m_场景物体网格指针, 几何ID, mesh);

			++offset;
		}
		break;
	}
	
	default:
		break;
	}

	for (auto& ob : ob->m_子物体) {
		f_构建顶层光追加速结构(ob, offset);
	}
}









void S_Scene::f_add物体(S_物体* ob) {
	switch (ob->m_Type) {
	case E_物体类型::t_多边形:
	case E_物体类型::t_网格:
	case E_物体类型::t_空:
		m_物体.push_back(ob);
		
		ob->m_isUpdate = true;
		ob->m_UpdateGPU参数布局 = true;
	default:
		break;
	}
}

void S_Scene::f_add物体(const std::vector<S_物体*> obs, E_场景物体容器类型 type) {
	switch (type) {
	case e_链表:
		break;
	case e_数组:
		break;
	case e_映射:
		break;
	case e_集合:
		for (auto& ob : obs) {
			switch (ob->m_Type) {
			case E_物体类型::t_平行光: {
				if (m_灯光.find(ob) == m_灯光.end()) {
					m_灯光.insert(ob);
					//ob->m_ID = m_平行光ID生成器.f_Gen();
					f_ob_fromLigthSceneData(ob)->mf_Update = f_平行光更新光照信息;
					f_ob_fromLigthSceneData(ob)->m_光追后端 = m_光追后端;
					m_重新录制光追灯光 = true;
				}
				break;
			}
			case E_物体类型::t_点光源: break;
			case E_物体类型::t_聚光灯: break;
			case E_物体类型::t_区域光: break;

			case E_物体类型::t_网格:
			case E_物体类型::t_多边形:
				if (m_物体set.find(ob) == m_物体set.end()) {
					//ob->m_ID = m_几何ID生成器.f_Gen();
					//S_物体::g_包围盒物体->m_变换矩阵块 = f_buf_galloc(S_物体::g_包围盒物体->m_变换矩阵, ob->m_globalID);
					//S_物体::g_包围盒物体->m_实例数量 = m_物体set.size();
				}
				m_重新录制绘图命令 = true;

			case E_物体类型::t_包:
			case E_物体类型::t_空:
			//case E_物体类型::t_虚拟体:
			case E_物体类型::t_灯光:
			case E_物体类型::t_骨架:
				m_物体set.insert(ob);
				break;

			default:
				break;
			}
			
			
			ob->m_isUpdate = true;
			ob->m_UpdateGPU参数布局 = true;
		}
		break;
	default:
		break;
	}

	
}

void S_Scene::f_remove物体(S_物体* ob, E_场景物体容器类型 type) {
	switch (type) {
	case e_链表:
		break;
	case e_数组:
		break;
	case e_映射:
		break;
	case e_集合:
		if (m_物体set.find(ob) != m_物体set.end()) {
			switch (ob->m_Type)
			{
			case E_物体类型::t_网格:
			case E_物体类型::t_多边形:
				//m_几何ID生成器.f_Move(ob->m_ID);
				//S_物体::g_包围盒物体->m_变换矩阵块 = f_buf_gfree(S_物体::g_包围盒物体->m_变换矩阵, 0);
				//S_物体::g_包围盒物体->m_实例数量 = m_物体set.size();
			default:
				break;
			}

			m_重新录制绘图命令 = true;
			m_物体set.erase(ob);
		}
		break;
	default:
		break;
	}
}

void S_Scene::f_remove物体(std::vector<S_物体*>& obs, E_场景物体容器类型 type) {
	switch (type)
	{
	case e_链表:
		break;
	case e_数组:
		break;
	case e_映射:
		break;
	case e_集合:
		for (auto& ob : obs) {
			switch (ob->m_Type) {
			case E_物体类型::t_平行光: {
				if (m_灯光.find(ob) != m_灯光.end()) {
					m_灯光.erase(ob);
					m_重新录制绘图命令 = true;
				}
				break;
			}
			case E_物体类型::t_点光源: break;
			case E_物体类型::t_聚光灯: break;
			case E_物体类型::t_区域光: break;

			default:
				if (m_物体set.find(ob) != m_物体set.end()) {
					m_物体set.erase(ob);
					m_重新录制绘图命令 = true;
				}
				break;
			}
			
		}
		
		break;
	default:
		break;
	}
}

vec3 S_Scene::f_get屏幕坐标到空间(S_摄像机* camera, const vec3& pos, const S_Rect2Df& view) {
	vec3 coord = f_UpProject还原空间顶点(pos, camera->m_相机投影, (float32*)&camera->m_相机位置矩阵, view);
	return coord;
}

/*std::vector<S_物体*> S_Scene::f_拾取(const vec3& s, const vec3& e, bool 是否多个) {
	std::vector<S_物体*> pickObjs;

	for (auto& obj : m_物体set) {
		if (obj->m_可拾取) {
			auto* m = f_ob_fromMesh(obj);
			//f_surface_射线相交()
			if (m) m->f_拾取(s, e);
		}
	}

	return pickObjs;
}*/

void S_Scene::f_构建物体空间树(float32 最小单元) {
	f_空间划分_set叉树空间大小(m_拾取树, 1000000.0, {});

	f_空间划分_remove所有子集(m_拾取树);

	for (auto& obj : m_物体set) {
		S_VecSphere c = f_ob_get范围(obj);
		auto* 单元 = f_空间划分_add子集(m_拾取树, c.pos, DEF_Max(最小单元, c.radius));
		if (单元->m_数据 == nullptr) {
			单元->m_数据 = new std::vector<S_物体*>();
		}
		((std::vector<S_物体*>*)单元->m_数据)->push_back(obj);
	}

}







S_Gpu相交拾取计算::S_Gpu相交拾取计算(S_设备环境& ctx) {
	std::vector<S_着色器创建参数> 参数配置;

	参数配置 = {
		{0, E_着色阶段::e_计算着色, E_板载缓存类型::e_SSBO},
		{1, E_着色阶段::e_计算着色, E_板载缓存类型::e_SSBO},
		{2, E_着色阶段::e_计算着色, E_板载缓存类型::e_SSBO},

		{3, E_着色阶段::e_计算着色, E_板载缓存类型::e_SSBOd},
	};

	m_GpuCtx_坐标_法线_UV = f_gpu_create并行计算实例(ctx, S_引擎配置::m_3D着色器文件根路径 + "射线相交网格.spv", 参数配置);
	
	m_属性参数 = f_buf_create板载缓存(m_GpuCtx_坐标_法线_UV->m_Ctx, E_板载缓存类型::e_SSBO, sizeof(S_Pick));
	m_相交数据 = f_buf_create板载缓存(m_GpuCtx_坐标_法线_UV->m_Ctx, E_板载缓存类型::e_SSBOd, sizeof(vec4));
	//S_Gpu实例拾取信息 拾取属性参数 = { mat, s, dir };
	//f_buf_fill板载缓存(拾取属性, &拾取属性参数, sizeof(S_GpuPick));
	//auto* g_索引 = f_buf_create板载缓存(*m_GpuCtx_坐标_法线_UV->m_Ctx, E_板载缓存类型::e_SSBO, sizeof(uvec3));
	m_参数元素[0] = f_buf_create板载缓存(m_GpuCtx_坐标_法线_UV->m_Ctx, E_板载缓存类型::e_SSBO, sizeof(vec3));
	//m_参数元素[1] = g_索引;
	m_参数元素[2] = m_属性参数;
	m_参数元素[3] = m_相交数据;

	m_布局位置[0] = 0;
	m_布局位置[1] = 1;
	m_布局位置[2] = 2;
	m_布局位置[3] = 3;
}

uvec3 S_Gpu相交拾取计算::f_updateGPU参数(S_板载缓存* 顶点, S_GPU内存块索引& 索引, S_Pick& info, E_顶点组合标志 顶点标志) {
	uvec3 dim = {1,1,1};
	dim.x = 索引.m_Mem.m_大小 / 3;

	f_buf_fill板载缓存(m_属性参数, &info, 1);
	f_buf_resize(m_相交数据, dim.x);
	
	//f_buf_copy板载缓存(m_参数元素[0], 顶点);
	//f_buf_copy(m_参数元素[1], *索引);
	//f_buf_copy板载缓存(m_参数元素[1], 索引);
	//m_参数元素[0] = 顶点;
	//m_参数元素[1] = 索引;
	m_参数元素[1] = 索引.m_Buf;

	m_数据偏移.VertOffset = 0;
	m_数据偏移.IndexOffset = 索引.m_Mem.m_偏移;


	switch (顶点标志) {
	case E_顶点组合标志::e_坐标_法线_UV: {
		std::vector<vec3> vert;
		f_setGPU参数布局(m_GpuCtx_坐标_法线_UV, { m_参数元素, 0, m_布局位置, 4, 0 });
		break;
	}
	default:
		break;
	}

	return dim;
}


S_拾取信息 f_surface_Gpu射线拾取面(S_Mesh* m, const vec3& s, const vec3& e, Mat44f& 变换) {
	S_拾取信息 pick_info = { {}, -1, -1 };
	//auto* m = f_ob_fromMesh(ob);
	//assert(m);
	static S_Gpu相交拾取计算* GPU设备 = new S_Gpu相交拾取计算(m->m_Ctx);

	S_Pick info;
	info.matrix = *((mat4*)&变换);
	info.s = { s.x, s.y, s.z, 1 };
	info.dir = { e.x, e.y, e.z, 1 };
	info.indexOffset = m->m_索引->m_Mem.m_偏移 / 3;
	info.vertOffset = 0;
	
	std::vector<vec3> vert;
	f_surface_get顶点坐标(m, vert);
	f_buf_fill板载缓存(GPU设备->m_参数元素[0], vert);
	
	//std::vector<uvec3> 索引;
	//f_surface_get顶点索引(m, 索引);
	uvec3 dim = GPU设备->f_updateGPU参数(m->m_顶点->m_Buf, *m->m_索引, info, E_顶点组合标志::e_坐标_法线_UV);
	f_GPU_run计算(GPU设备->m_GpuCtx_坐标_法线_UV, dim);



	GPU设备->m_参数元素[3]->f_map();
	S_VecSphere* pick = (S_VecSphere*)(GPU设备->m_参数元素[3]->m_mappedPtr);

	float32 mindir = 90000000;
	for (uint32 i = 0; i < dim.x; ++i) {
		if (pick[i].radius >= 0 && pick[i].radius < mindir) {
			mindir = pick[i].radius;
			pick_info.元素索引 = i;
		}
	}

	if (pick_info.元素索引 < -1) {
		pick_info.相交坐标 = pick[pick_info.元素索引].pos;
		pick_info.相交距离 = vec_len(pick[pick_info.元素索引].pos - s);
	}
	
	GPU设备->m_参数元素[3]->f_unmap();

	return pick_info;
}




S_物体拾取信息 f_scene_射线拾取物体(S_物体* ob, const vec3& s, const vec3& dir, S_Mesh* mesh, Mat44f* 父级变换) {
	S_物体拾取信息 物体拾取信息 = { nullptr, -1, 100000000 };
	vec3 交点 = {};
	float32 当前距离 = 100000000;


	Mat44f* 当前矩阵prt = 父级变换;
	if (ob->m_变换矩阵.m_Mem.m_大小) {
		当前矩阵prt = f_buf_Mat44_ptr(ob->m_变换矩阵);
	}

	Mat44f& mat = 当前矩阵prt[ob->m_实例ID];




	if (!mesh) {
		auto me = f_ob_fromMesh(ob, 0);
		if(me) mesh = me;
	}

	if (mesh && ob->m_渲染) {
		vec3 size = (mesh->m_Bound.max - mesh->m_Bound.min);
		
		float32 距离 = f_graph_点到直线距离(s, dir, mat * vec3{0,0,0});
		//float32 距离 = f_graph_点到直线距离(s, dir, mesh->m_包围盒.pos);


		if (ob->m_是否实例) {
			size = { 1,1,1 };
		}
		else {
			size = f_mat44_to_33(mat) * size;

			//size = vec3{ ob->m_包围盒.size.x, ob->m_包围盒.size.y, ob->m_包围盒.size.z };
			size = vec_abs(size);
			switch (ob->m_Type) {
			case E_物体类型::t_灯光:
			case E_物体类型::t_包:
				break;
			default:
				if (距离 >= vec_Max(size)) {
					goto To_子集;
				}
				break;
			}
		}

		


		
		float32* 独立缩放 = nullptr;
		


		switch (ob->m_Type) {
		case E_物体类型::t_骨架:
		//	if (ob->m_实例数量 >= 1) break;
		case E_物体类型::t_骨骼: {
			独立缩放 = f_buf_F32_ptr(ob->m_骨架->m_骨骼长度);
			uint32 num = ob->m_骨架->m_骨骼长度.m_Mem.m_大小;
			
			if (f_surface_射线面相交(mesh, mat, 独立缩放[ob->m_实例ID], s, dir, 交点, 当前距离)) {
				if (当前距离 < 物体拾取信息.相交距离) {
					物体拾取信息.相交距离 = 当前距离;
					物体拾取信息.实例ID = ob->m_实例ID;
					物体拾取信息.物体 = ob;
				}
			}
			break;
		}

		case E_物体类型::t_多边形:
		case E_物体类型::t_网格:
			//跳到实例 当个实例处理
			if (ob->m_变换矩阵.m_Mem.m_大小 > 1) break;

		case E_物体类型::t_实例: {
			if (mesh->m_索引->m_Mem.m_大小 > 10000) {
				S_拾取信息 pick_info = f_surface_Gpu射线拾取面(mesh, s, dir, mat);
				if (pick_info.相交距离 >= 0) {
					物体拾取信息.相交距离 = (pick_info.相交距离);
					物体拾取信息.实例ID = ob->m_实例ID;
					物体拾取信息.物体 = ob;
				}
			}
			else {
				if (f_surface_射线面相交(mesh, mat, 1.0f, s, dir, 交点, 当前距离)) {
					//std::cout<<"当前距离 = " << 当前距离 << std::endl;
					if (当前距离 < 物体拾取信息.相交距离) {
						物体拾取信息.相交距离 = 当前距离;
						物体拾取信息.实例ID = ob->m_实例ID;
						物体拾取信息.物体 = ob;
					}
				}
			}
			break;
		}
		
		case E_物体类型::t_线段: {
			for (uint32 i = 0; i < mesh->m_间接->m_Mem.m_大小; ++i) {
				S_线拾取 info = f_surface_线段相交(mesh, mat, s, dir, 当前距离, i);
				if (info.相交距离 < g线拾取距离) {
					if (当前距离 < 物体拾取信息.相交距离) {
						物体拾取信息.相交距离 = 当前距离;
						物体拾取信息.实例ID = ob->m_实例ID;
						物体拾取信息.物体 = ob;
					}
				}
			}
			break;
		}

		case E_物体类型::t_虚拟体:
		case E_物体类型::t_区域光_方形:
		case E_物体类型::t_区域光_圆形:
		case E_物体类型::t_平行光:
		case E_物体类型::t_聚光灯:
		case E_物体类型::t_区域光:
		//case E_物体类型::t_点光源:
		//case E_物体类型::t_包: 
		{
			Mat44f 当前变换 = mat;
			S_摄像机* 摄像机 = dynamic_cast<S_摄像机*>(f_ob_get子对象(ob, 0));
			if (摄像机) {
				当前变换 = mat * f_mat44_构建缩放矩阵(f_camera_计算摄像机以角度缩放大小(摄像机));
			}
			
			if (mesh->m_间接) {
				//const auto& indirect = f_buf_at_Indirect(*mesh->m_间接, ob->m_实例ID);
				S_线拾取 info = f_surface_线段相交(mesh, 当前变换, s, dir, 当前距离, ob->m_实例ID);
				if (info.相交距离 < g线拾取距离) {
					物体拾取信息.相交距离 = 当前距离;
					物体拾取信息.实例ID = ob->m_实例ID;
					物体拾取信息.物体 = ob;
				}
			}
			else {
				S_线拾取 info = f_surface_线段相交(mesh, 当前变换, s, dir, 当前距离, ob->m_实例ID);
				if (info.相交距离 < g线拾取距离) {
					物体拾取信息.相交距离 = 当前距离;
					物体拾取信息.实例ID = ob->m_实例ID;
					物体拾取信息.物体 = ob;
				}
			}
			
			break;
		}

		/*case E_物体类型::t_区域光_方形:
		case E_物体类型::t_区域光_圆形:
		case E_物体类型::t_平行光:
		case E_物体类型::t_聚光灯:
		case E_物体类型::t_区域光:*/
		case E_物体类型::t_点光源:{
			//距离 = f_graph_点到直线距离(s, dir, ob->m_包围盒.pos);
			vec3 location = f_ob_get全局坐标(ob, ob->m_实例ID);
			距离 = f_graph_点到直线距离(s, dir, location);
			//std::cout << "距离 = " << 距离 << std::endl;
			if (距离 < vec_Max(ob->m_变换.scale) + 0.1) {
				距离 += vec_len(s - location);

				物体拾取信息.相交距离 = 距离;
				物体拾取信息.实例ID = ob->m_实例ID;
				物体拾取信息.物体 = ob;
			}
			break;
		}

		default:
			break;
		}
	}


	To_子集:
	uint32 num = ob->m_子物体.size();
	auto* obs = ob->m_子物体.data();
	for (uint32 i = 0; i < num; ++i) {
		S_物体拾取信息 info;
		switch (obs[i]->m_Type) {
		//case E_物体类型::t_区域光_方形:
		//case E_物体类型::t_区域光_圆形:
		//case E_物体类型::t_平行光:
		//case E_物体类型::t_聚光灯:
		//case E_物体类型::t_区域光:
		//case E_物体类型::t_点光源:
		//case E_物体类型::t_包:
		case E_物体类型::t_线段: {
			for (uint32 k = 0; k < obs[i]->m_DataNum; ++k) {
				auto* m = f_ob_fromMesh(obs[i], k);
				info = f_scene_射线拾取物体(obs[i], s, dir, m, 当前矩阵prt);
				if (info.物体 && info.相交距离 <= 物体拾取信息.相交距离) {
					物体拾取信息 = info;
				}
			}
			break;
		}
		
		default: {
			info = f_scene_射线拾取物体(obs[i], s, dir, mesh, 当前矩阵prt);
			if (info.物体 && info.相交距离 <= 物体拾取信息.相交距离) {
				物体拾取信息 = info;
			}
			break;
		}
		}
	}

	if (物体拾取信息.物体 && (ob->m_Type == E_物体类型::t_物体包 || ob->m_Type == E_物体类型::t_骨架)) {
		物体拾取信息.物体 = ob;
	}


	return 物体拾取信息;
}

S_物体拾取信息 f_scene_射线拾取物体AABB(S_物体* ob, const vec3& s, const vec3& dir, S_Mesh* mesh, Mat44f* mat) {
	S_物体拾取信息 物体拾取信息 = { nullptr, -1, 100000000 };

	uint32 num = ob->m_子物体.size();
	auto* obs = ob->m_子物体.data();
	for (uint32 i = 0; i < num; ++i) {

	}

	return S_物体拾取信息();
}

void f_平行光更新光照信息(void* data) {
	auto 属性 =f_ob_fromParallelLigth(((S_灯光场景数据*)data)->m_灯光);
	f_buf_set(((S_灯光场景数据*)data)->m_光追后端->m_平行光缓冲区, ((S_灯光场景数据*)data)->m_灯光->m_ID, *属性);

	//S_LigthParallel* prop = f_buf_map板载缓存<S_LigthParallel>(((S_灯光场景数据*)data)->m_光追后端->m_平行光缓冲区);
	//(*prop) = (*属性);
	//f_buf_unmap板载缓存(((S_灯光场景数据*)data)->m_光追后端->m_平行光缓冲区);
	((S_灯光场景数据*)data)->m_光追后端->f_重置渲染帧记录();

}


void f_scene_构建顶层光追加速结构(S_Scene* scene, S_OBArray* obs, S_设备环境& ctx) {
	std::vector<S_GPU内存块索引> 光追实例加速结构;
	光追实例加速结构.reserve(obs->count);

	for (uint32 i = 0; i < obs->count; ++i) {
		if (obs->ptr_userData[i]->m_光追实例加速结构.m_Mem.m_大小) {
			光追实例加速结构.push_back(obs->ptr_userData[i]->m_光追实例加速结构);
		}
	}

	if (obs->count) {
		f_df_构建顶层光追加速(ctx, 光追实例加速结构, scene->m_光追顶层加速结构);
	}
}

